﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Reflection;
using System.Web.Http.Dependencies;
using System.Web.Mvc;
using PAMD.Controllers;
using PAMD.Data.Ajax.Services.Controllers;
using PAMD.Database.Services;
using IDependencyResolver = System.Web.Http.Dependencies.IDependencyResolver;

namespace PAMD.App_Start
{
    public static class MefConfig
    {
        public static void RegisterMef()
        {
            var container = ConfigureContainer();
            ControllerBuilder.Current.SetControllerFactory(new MefControllerFactory(container));
            System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new MefDependencyResolver(container);
        }

        private static CompositionContainer ConfigureContainer()
        {
            AssemblyCatalog assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
            AssemblyCatalog libClient = new AssemblyCatalog(typeof(CommonController).Assembly);
            AssemblyCatalog controllers = new AssemblyCatalog(typeof(HomeController).Assembly);
            AssemblyCatalog lib = new AssemblyCatalog(typeof(CommonService).Assembly);

            AggregateCatalog aggregateCatalog = new AggregateCatalog();
            aggregateCatalog.Catalogs.Add(assemblyCatalog);
            aggregateCatalog.Catalogs.Add(controllers);
            aggregateCatalog.Catalogs.Add(libClient);
            aggregateCatalog.Catalogs.Add(lib);

            var container = new CompositionContainer(aggregateCatalog);

            return container;
        }
    }

    public class MefDependencyResolver : IDependencyResolver
    {
        private readonly CompositionContainer _container;

        public MefDependencyResolver(CompositionContainer container)
        {
            _container = container;
        }

        public IDependencyScope BeginScope()
        {
            return this;
        }

        public object GetService(Type serviceType)
        {
            var export = _container.GetExports(serviceType, null, null).SingleOrDefault();

            return null != export ? export.Value : null;
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            var exports = _container.GetExports(serviceType, null, null);
            var createdObjects = new List<object>();

            if (exports.Any())
            {
                createdObjects.AddRange(exports.Select(export => export.Value));
            }

            return createdObjects;
        }

        public void Dispose()
        {
           
        }
    }

    public class MefControllerFactory : DefaultControllerFactory
    {
        private readonly CompositionContainer _compositionContainer;

        public MefControllerFactory(CompositionContainer compositionContainer)
        {
            _compositionContainer = compositionContainer;
        }

        protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
        {
            if (controllerType == null)
            {
                controllerType = typeof(ErrorController); 
            }

            var export = _compositionContainer.GetExports(controllerType, null, null).SingleOrDefault();

            IController result;

            if (null != export)
            {
                result = export.Value as IController;
            }
            else
            {
                result = base.GetControllerInstance(requestContext, controllerType);
                _compositionContainer.ComposeParts(result);
            }

            return result;
        }
    }
}